﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.ComponentModel;
using System.Web.Mvc;

using Seven.Site.Mvc.Attributes;
using Seven.Site.Models.ControllerActionModel;

namespace Seven.Site.Mvc
{
    public class ControllerActionGetter
    {
        /// <summary>
        /// 获取所有的控制器集合
        /// </summary>
        /// <param name="assemblyname">程序集名称</param>
        /// <returns></returns>
        public static List<ControllerModel> GetControllersByAssembly(string assemblyname)
        {
            var Controllers = new List<ControllerModel>();

            var Types = Assembly.Load(assemblyname).GetTypes();
            string BaseTypeName = typeof(BaseController).Name; int len = ("Controller").Length;
            foreach (var type in Types)
            {
                if (type.BaseType != null && type.BaseType.Name == BaseTypeName)
                {
                    var Controller = new ControllerModel();
                    Controller.ControllerName = type.Name.Substring(0, type.Name.Length - len);
                    object[] attrs = type.GetCustomAttributes(typeof(DescriptionAttribute), true);
                    if (attrs.Length > 0)
                    {
                        Controller.Description = (attrs[0] as DescriptionAttribute).Description;
                    }
                    Controllers.Add(Controller);
                }
            }
            return Controllers;
        }

        /// <summary>
        /// 根据控制器名称获取其Action集合
        /// </summary>
        /// <param name="assemblyname">程序集名称</param>
        /// <param name="controllername">控制器名称</param>
        /// <returns></returns>
        public static List<ActionModel> GetActionsByAssembly(string assemblyname, string controllername)
        {
            var Actions = new List<ActionModel>();

            var Types = Assembly.Load(assemblyname).GetTypes();
            string BaseTypeName = typeof(BaseController).Name; int len = ("Controller").Length;
            foreach (var type in Types)
            {
                if (type.BaseType != null && type.BaseType.Name == BaseTypeName)
                {
                    string ControllerName = type.Name.Substring(0, type.Name.Length - len);
                    if (ControllerName == controllername)
                    {
                        Actions.AddRange(GetActionsByControllerType(type));
                        break;
                    }
                }
            }
            return Actions;
        }

        /// <summary>
        /// 根据控制器Type获取所有的Action
        /// </summary>
        /// <param name="type">控制器类型</param>
        /// <returns></returns>
        public static List<ActionModel> GetActionsByControllerType(Type type)
        {
            var Members = type.GetMethods();
            var Actions = new List<ActionModel>(); int len = ("Controller").Length;
            string ControllerName = type.Name.Substring(0, type.Name.Length - len);
            string ResultName1 = typeof(ViewResult).Name, ResultName2 = typeof(PartialViewResult).Name, ResultName3 = typeof(JsonResult).Name;
            string[] ResultNames = new string[3] { ResultName1, ResultName2, ResultName3 };
            foreach (var member in Members)
            {
                //只获取返回类型符合要求的Action
                if (ResultNames.Contains(member.ReturnType.Name))
                {
                    var Action = new ActionModel();
                    Action.ActionName = member.Name;
                    Action.ControllerName = ControllerName;
                    object[] attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), true);
                    if (attrs.Length > 0)
                    {
                        Action.Description = (attrs[0] as DescriptionAttribute).Description;
                    }
                    Action.IsViewPageAction = member.GetCustomAttributes(typeof(ViewPageAttribute), true).Length > 0;

                    Actions.Add(Action);
                }
            }
            return Actions;
        }
    }
}
